/**************************************************************************************************
* Title: SumCamera.h
* Author: Gael Huber
* Description: Describes a basic camera class
**************************************************************************************************/
#ifndef __SUMCAMERA_H__
#define __SUMCAMERA_H__

#include "SumMath.h"

class Camera {
public:
	// Default constructor
	Camera(void);

	// Constructor defining primary characteristics of viewing frustrum
	Camera(float fov, float aspect, float zn, float zf);

	// Copy constructor
	Camera(const Camera& rhs);

	// Destructor
	virtual ~Camera(void);

	// Given an axis and an angle, rotate the camera
	void rotate(const Vector3_16f& axis, float angle);

	// Rotate the camera by a quaternion
	void rotate(const Quaternion_16f& q);

	// Give the camera a yaw about the Y axis
	void yaw(float angle);

	// Give the camera a yaw about the local Y axis
	void yawRelative(float angle);

	// Give the camera a pitch about the X axis
	void pitch(float angle);

	// Give the camera a pitch about the local X axis
	void pitchRelative(float angle);

	// Give the camera a roll about the Z axis
	void roll(float angle);

	// Give the camera a roll about the local Z axis
	void rollRelative(float angle);

	// Set the camera's orientation to a given quaternion
	void setOrientation(const Quaternion_16f& q);

	// Gets the current orientation
	const Quaternion_16f& getOrientation(void) const;

	// Look at a given location in space
	void lookAt(const Vector3_16f& pos);

	// Look at a given location in space
	void lookAt(float x, float y, float z);

	// Get the forward direction the camera is facing
	Vector3_16f getDirection(void) const;

	// Get the vector pointing right compared to the forward
	Vector3_16f getRight(void) const;

	// Get the up vector
	Vector3_16f getUp(void) const;

	// Move the camera by an absolute distance relative to world axes
	void move(const Vector3_16f& dist);

	// Move the camera by an absolute distance relative to world axes
	void move(float x, float y, float z);

	// Move the camera by an absolute distance relative to the camera orientation
	void moveRelative(const Vector3_16f& dist);

	// Move the camera by an absolute distance relative to the camera orientation
	void moveRelative(float x, float y, float z);

	// Get the camera position
	const Vector3_16f getPosition(void) const;

	// Set the absolute position
	void setPosition(const Vector3_16f& pos);

	// Set the absolute position
	void setPosition(float x, float y, float z);

	// Get the projection matrix
	const Matrix_16f& getProjectionMatrix(void) const;

	// Get the view matrix
	const Matrix_16f& getViewMatrix(void) const;

	// Get the combination of the view and projection matrix
	Matrix_16f getViewProjMatrix(void) const;

	// Update the view matrix based on current camera data
	void updateView(void);

private:
	Vector3_16f position;		// Camera position
	Quaternion_16f orientation;	// Current camera orientation
	Matrix_16f projection;		// Projection matrix
	Matrix_16f view;			// View matrix

	float fov;					// Field of view
	float aspect;				// Aspect ratio
	float nearPlane;			// Near clipping plane
	float farPlane;				// Far clipping plane
};

#endif